package cn.szsys.integration.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * @author Ryan
 * @since 2025-05-08
 **/
public class Base64Util {
    private static Logger log = LoggerFactory.getLogger(Base64Util.class);
    /**
     * base64编码前缀
     */
    private static final String BASE64_IMG_PNG_PREFIX = "data:image/png;base64,";

    private static Base64.Decoder DECODER = Base64.getDecoder();
    private static Base64.Encoder ENCODER = Base64.getEncoder();

    private static Base64.Decoder MIME_DECODER = Base64.getMimeDecoder();

    /**
     * 转换为base64编码
     * @author Ryan
     * @param bs bs
     * @return {@link String}
     */
    public static String encode(byte [] bs) {
        return new String(ENCODER.encode(bs), StandardCharsets.UTF_8);
    }

    /**
     * 转换为base64编码
     * @author Ryan
     * @param source source
     * @return {@link String}
     */
    public static String encode(String source) {
        return new String(ENCODER.encode(source.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
    }

    /**
     * base64编码还原
     * @author Ryan
     * @param str str
     * @return {@link byte[]}
     */
    public static byte[] decode(String str) {
        return DECODER.decode(str.getBytes(StandardCharsets.UTF_8));
    }

    /**
     * base64编码还原
     * @author Ryan
     * @param str str
     * @param cs cs
     * @return {@link byte[]}
     */
    public static byte[] decode(String str, Charset cs) {
        return DECODER.decode(str.getBytes(cs));
    }


    /**
     * base64编码还原
     * @author Ryan
     * @param str str
     * @return {@link String}
     */
    public static String decode2Str(String str) {
        return new String(DECODER.decode(str.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8);
    }

    public static String img2Base64(BufferedImage bImg) {
        try {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            ImageIO.write(bImg, "png", outputStream);
            String base64Img = encode(outputStream.toByteArray());
            base64Img = base64Img.replaceAll("\n", "").replaceAll("\r", "");
            base64Img = BASE64_IMG_PNG_PREFIX + base64Img;
            return base64Img;
        } catch (Exception e) {
            log.error("二维码图片转base64编码出错", e);
            return null;
        }
    }

    /**
     * base64编码还原
     * @author Ryan
     * @param str str
     * @param cs cs
     * @return {@link byte[]}
     */
    public static byte[] mimeDecode(String str, Charset cs) {
        return MIME_DECODER.decode(str.getBytes(cs));
    }

    /**
     * 将图片URL转换为Base64编码字符串
     * @param imageUrl 图片URL地址
     * @return 完整的Base64编码图片字符串(data:image/[type];base64,...)
     * @throws IOException 网络请求或图片处理异常
     */
    public static String imageUrlToBase64(String imageUrl) throws IOException {
        URL url = new URL(imageUrl);
        try (InputStream in = url.openStream();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }

            byte[] imageBytes = out.toByteArray();
            if (imageBytes.length == 0) {
                throw new IOException("Empty image data from URL: " + imageUrl);
            }

            // 检测图片类型
            String imageType = detectImageType(imageBytes);
            if (imageType == null) {
                throw new IOException("Unsupported image type from URL: " + imageUrl);
            }

            // Base64编码
            String base64 = ENCODER.encodeToString(imageBytes);
            return "data:image/" + imageType + ";base64," + base64;
        } catch (Exception e) {
            log.error("Failed to convert image URL to Base64: " + imageUrl, e);
            throw new IOException("Failed to convert image URL to Base64: " + imageUrl, e);
        }
    }

    private static String detectImageType(byte[] imageBytes) {
        if (imageBytes.length >= 2) {
            if (imageBytes[0] == (byte) 0xFF && imageBytes[1] == (byte) 0xD8) {
                return "jpeg";
            } else if (imageBytes[0] == (byte) 0x89 && imageBytes[1] == (byte) 0x50) {
                return "png";
            } else if (imageBytes[0] == (byte) 0x47 && imageBytes[1] == (byte) 0x49) {
                return "gif";
            } else if (imageBytes[0] == (byte) 0x42 && imageBytes[1] == (byte) 0x4D) {
                return "bmp";
            }
        }
        return null;
    }
}
